/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Negocio;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 *
 * @author Ivan
 */
public class ArbolBusqueda {
    private Hoja raiz;
    private int niveles;
    private List<Hoja> caminoOptimo;
    private MetodoBusqueda metodo;

    public ArbolBusqueda(Hoja raiz, int niveles, List<Hoja> caminoOptimo, MetodoBusqueda metodo) {
        this.raiz = raiz;
        this.niveles = niveles;
        this.caminoOptimo = caminoOptimo;
        this.metodo = metodo;
    }

    public ArbolBusqueda() {
        raiz=null;
        niveles=-1;
        caminoOptimo = new ArrayList<Hoja>();
        metodo=null;
    }

    public MetodoBusqueda getMetodo() {
        return metodo;
    }

    public void setMetodo(MetodoBusqueda metodo) {
        this.metodo = metodo;
    }

   
    public List<Hoja> getCaminoOptimo() {
        return caminoOptimo;
    }

    public void setCaminoOptimo(List<Hoja> caminoOptimo) {
        this.caminoOptimo = caminoOptimo;
    }

    public int getNiveles() {
        return niveles;
    }

    public void setNiveles(int niveles) {
        this.niveles = niveles;
    }

    public Hoja getRaiz() {
        return raiz;
    }

    public void setRaiz(Hoja raiz) {
        this.raiz = raiz;
    }

    public void generarArbol(){
        raiz=new Hoja();
        raiz.setEstado(metodo.getEstadoInicial());
        metodo.obtenerMetrica(raiz);
        cargarHijos(raiz);



    }

    private void cargarHijos(Hoja hoja){

        if(esEstadoFinal(hoja))
            return;
        if(hoja.getNivelHoja()>niveles)
            return;


        List<Estado> estadosHijos= estados(hoja.getEstado());
        
        Hoja temp=null;

        for(int i=0; i < estadosHijos.size(); i++){
            temp=new Hoja();
            temp.setPadre(hoja);
            temp.setEstado(estadosHijos.get(i));
            temp.setNivelHoja(hoja.getNivelHoja()+1);

            hoja.agregarHijo(temp);
            ///--------------

            metodo.obtenerMetrica(temp);
            cargarHijos(temp);
        }

//        List<Hoja> hojaHijos=new ArrayList<Hoja>();
//        hojaHijos=hoja.getHijos();
//
//        for(int i=0; i < hojaHijos.size();i++)
//        {
//            metodo.obtenerMetrica(hojaHijos.get(i));
//            cargarHijos(hojaHijos.get(i));
//        }

    }
    
    private List<Estado> estados(Estado estado){
        
         List<Estado> estadosHijos= metodo.obtenerEstados(estado);
         return estadosHijos;
    }



    private boolean esEstadoFinal(Hoja hoja){
           return hoja.getEstado().isEsFinal();
        
    }


    public void inicializarArbol(){
        raiz=new Hoja();
        raiz.setEstado(metodo.getEstadoInicial());
        metodo.obtenerMetrica(raiz);
    }
    public void cargarHijosDinamico(Hoja hoja){

        if(hoja.getEstado().isEsFinal())
            return;

        if(!hoja.getHijos().isEmpty())
            return;
          List<Estado> estadosHijos= metodo.obtenerEstados(hoja.getEstado());

        Hoja temp=null;

        for(int i=0; i < estadosHijos.size(); i++){
            temp=new Hoja();
            temp.setPadre(hoja);
            temp.setEstado(estadosHijos.get(i));
            temp.setNivelHoja(hoja.getNivelHoja()+1);
            metodo.obtenerMetrica(temp);

            if(!existe(temp))
                hoja.agregarHijo(temp);
            ///--------------
            

        }
    }

    public boolean existe(Hoja hoja){

        if(raiz.esIgual(hoja))
            return true;


        for(int i=0; i<raiz.getHijos().size();i++){
            if(existeRecursivo(raiz.getHijos(i),hoja))
                return true;
       }
        return false;
    }
    public boolean existeRecursivo(Hoja aPartir, Hoja hojaexiste){
        
      
        LinkedList<Hoja> lista=new LinkedList();
        lista.addFirst(aPartir);
        
        while(lista.size()>0)
        {            
            if(lista.getFirst().equals(hojaexiste)==true)
                return true;
            lista.addAll(lista.removeFirst().getHijos()); 
        }
        return false;
      
       
        
//
//       if(aPartir.esIgual(hojaexiste))
//           return true;
//
//        for(int i=0; i<aPartir.getHijos().size();i++){
//            if(existeRecursivo(aPartir.getHijos(i),hojaexiste))
//                return true;
//       }
//        return false;

    }

}
